package service

import (
	"errors"
	"github.com/kataras/iris/v12"
	"github.com/spf13/cast"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm/clause"
	"wit-admin-go/system/app/dto"
	"wit-admin-go/system/app/model"
	witJwt "wit-admin-go/system/jwt"
	"wit-admin-go/system/utils"
	log "wit-admin-go/system/zaplogger"
)

type userService struct{}

var UserService = new(userService)

// PostCreateUser  创建用户
func (us *userService) PostCreateUser(user dto.User) (err error) {
	role := new(dto.Role)
	if user.RoleId == "" {
		utils.DB.Find(&role, "sole = ?", "ordinary")
		user.Role = *role
	}
	err = utils.DB.Create(&user).Error
	if err != nil {
		log.Log.Error(err.Error())
		return err
	}
	// 关联角色接口权限
	if user.RoleId != "" {
		_, err = utils.WitEnforcer.AddRoleForUser(user.Id, user.RoleId)
		return err
	}
	_, err = utils.WitEnforcer.AddRoleForUser(user.Id, role.Id)
	return err
}

// PutUpdateUser 修改用户
func (us *userService) PutUpdateUser(user dto.UpdateUser) (err error) {
	users := new(model.User)
	_, errN := us.GetUserById(user.Id)
	if errN != nil {
		return errN
	}
	if user.RoleId != "" {
		_, _ = utils.WitEnforcer.DeleteRolesForUser(user.Id)
		_, err = utils.WitEnforcer.AddRoleForUser(user.Id, user.RoleId)
	}
	return utils.DB.Model(&users).Where("id = ?", user.Id).Updates(user).Error
}

// PutUpdateUserPassword 修改用户密码
func (us *userService) PutUpdateUserPassword(user dto.UpdateUserPassword) (err error) {
	_, errN := us.GetUserById(user.Id)
	if errN != nil {
		return errN
	}
	users := new(model.User)
	users.Password = user.Password
	users.UpdateId = user.UpdateId
	return utils.DB.Model(&users).Where("id = ?", user.Id).Updates(users).Error
}

// PutUpdatePassword 修改密码
func (us *userService) PutUpdatePassword(user dto.UpdatePassword) (err error) {
	old, errN := us.GetUserById(user.Id)
	if errN != nil {
		return errN
	}
	// 判断原密码
	err = bcrypt.CompareHashAndPassword([]byte(old.Password), []byte(user.Password))
	if err != nil {
		return errors.New("原密码错误！")
	}
	users := new(model.User)
	// 生成新密码
	password, _ := bcrypt.GenerateFromPassword([]byte(user.NewPassword), bcrypt.DefaultCost)
	users.Password = cast.ToString(password)
	users.UpdateId = user.UpdateId
	return utils.DB.Model(&users).Where("id = ?", user.Id).Updates(users).Error
}

// GetUserById 通过ID查询数据
func (us *userService) GetUserById(id string) (user model.User, err error) {
	err = utils.DB.Preload(clause.Associations).First(&user, "id = ?", id).Error
	if err != nil {
		return user, errors.New("数据没找到")
	}
	role, _ := RoleService.GetRoleById(user.RoleId)
	user.Role = role
	return user, err
}

// GetUserList 获取所有数据
func (us *userService) GetUserList(page *dto.UserPage) (*[]model.User, int64) {
	user := new([]model.User)
	db := utils.DB.Preload(clause.Associations)
	if page.UserName != "" {
		db = db.Where("user_name LIKE ?", "%"+page.UserName+"%")
	}
	if page.Name != "" {
		db = db.Where("user_name LIKE ?", "%"+page.Name+"%")
	}
	total := db.Scopes(utils.Paginate(page.PageNum, page.PageSize)).Preload("Role").Find(&user).RowsAffected
	if total > 0 {
		return user, total
	} else {
		return nil, 0
	}
}

// DelUser 删除数据
func (us *userService) DelUser(id string, userId string) (err error) {
	user, errN := us.GetUserById(id)
	if errN != nil {
		return errN
	}
	user.DeleteId = userId
	err = utils.DB.Delete(&user, "id = ?", id).Error
	return err
}

// RemoveUser 永久删除数据
func (us *userService) RemoveUser(id string) (err error) {
	user := new(model.User)
	err = utils.DB.Unscoped().Delete(&user, "id = ?", id).Error
	return err
}

// LogIn 登录
func (us *userService) LogIn(login dto.Login, ctx iris.Context) (err error) {
	user := new(model.User)
	db := utils.DB
	err = db.Where("user_name = ?", login.UserName).Or("phone = ?", login.UserName).Or("email = ?", login.UserName).Find(&user).Error
	//err = utils.DB.Find(&user, "user_name = ?", login.UserName).Error
	if err != nil {
		return err
	}
	err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(login.Password))
	if err != nil {
		return err
	}
	token := witJwt.GenerateToken(*user)
	_ = ctx.JSON(dto.NewResult(map[string]string{"token": token}, iris.StatusOK, "登录成功"))
	return nil
}
